﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using mal.WP7.Framework.Messages;
using mal.WP7.GoogleAnalytics.Business.Helpers;
using mal.WP7.GoogleAnalytics.Business.Repository;
using mal.WP7.GoogleAnalytics.Business.Tiles;

namespace mal.WP7.GoogleAnalytics.ViewModels.Dashboard
{
    public abstract class DashboardItemBase : ViewModelBase
    {
        #region Fields
        private string label;
        private ObservableCollection<DashboardRowViewModel> rows;
        private DashboardRowViewModel selectedRow;
        private bool isActive;
        private bool isLoading;
        private bool hasError;

        private TileManager tileManager;
        #endregion

        #region Construction / Destruction
        public DashboardItemBase()
        {
            this.tileManager = new TileManager();
            Messenger.Default.Register<WebsitesAvailableMessage>(this, this.OnWebsitesAvailable);
            Messenger.Default.Register<WebsiteStatisticsAvailableMessage>(this, this.OnWebsiteStatisticsAvailable);
        }
        #endregion

        #region enum, struct, class

        #endregion

        #region Properties
        public string Label
        {
            get
            {
                return this.label;
            }

            set
            {
                if (this.label != value)
                {
                    this.label = value;
                    RaisePropertyChanged("Label");
                }
            }
        }

        public ObservableCollection<DashboardRowViewModel> Rows
        {
            get
            {
                return this.rows;
            }

            protected set
            {
                if (this.rows != value)
                {
                    this.rows = value;
                    RaisePropertyChanged("Rows");
                }
            }
        }

        public bool IsActive
        {
            get
            {
                return this.isActive;
            }

            set
            {
                if (this.isActive != value)
                {
                    this.isActive = value;
                    RaisePropertyChanged("IsActive");
                }
            }
        }

        public bool IsLoading
        {
            get
            {
                return this.isLoading;
            }

            set
            {
                if (this.isLoading != value)
                {
                    this.isLoading = value;
                    RaisePropertyChanged("IsLoading");
                }
            }
        }

        public bool HasError
        {
            get
            {
                return this.hasError;
            }

            set
            {
                if (this.hasError != value)
                {
                    this.hasError = value;
                    RaisePropertyChanged("HasError");
                }
            }
        }

        public DashboardRowViewModel SelectedRow
        {
            get
            {
                return this.selectedRow;
            }

            set
            {
                if (this.selectedRow != value)
                {
                    this.selectedRow = value;
                    RaisePropertyChanged("SelectedRow");

                    if (this.selectedRow != null)
                    {
                        App.ViewModel.SelectedWebsiteId = this.selectedRow.WebsiteId;
                        Uri uri = new System.Uri(NavigationUriHelper.WebsitePageUrl(this.selectedRow.WebsiteId), UriKind.Relative);
                        NavigateMessage.Send(uri);
                    }
                }
            }
        }
        #endregion

        #region Methods
        public void LoadDatas()
        {
            this.LoadDatas(WebsiteRepository.Instance.Websites);
        }

        protected abstract void LoadDatas(Website website);

        protected abstract WebsiteStatisticsAvailableMessage.WebsiteStatisticsAvailableType GetWebsiteStatisticsAvailableType();

        private void LoadDatas(List<Website> websites)
        {
            if (websites != null)
            {
                this.IsLoading = false;
                foreach (Website website in websites)
                {
                    if (this.Rows == null)
                    {
                        this.Rows = new ObservableCollection<DashboardRowViewModel>();
                    }

                    DashboardRowViewModel row = this.Rows.FirstOrDefault(w => w.WebsiteId == website.Id);

                    if (row == null)
                    {
                        row = new DashboardRowViewModel();
                        row.WebsiteId = website.Id;
                        row.WebsiteName = website.Name;
                        this.Rows.Add(row);
                    }

                    this.LoadDatas(website);
                }
            }
            else
            {
                this.IsLoading = true;
            }
        }
        #endregion

        #region Events
        private void OnWebsitesAvailable(WebsitesAvailableMessage message)
        {
            if (this.isActive)
            {
                if (message.Error == null)
                {
                    this.LoadDatas(WebsiteRepository.Instance.Websites);
                }
                else
                {
                    this.IsLoading = false;
                }
            }
        }

        private void OnWebsiteStatisticsAvailable(WebsiteStatisticsAvailableMessage message)
        {
            if (message.Type == this.GetWebsiteStatisticsAvailableType())
            {
                if (message.Error == null)
                {
                    this.HasError = false;
                    this.LoadDatas(message.Website);

                    // TODO : it is not the best place to refresh live tiles.
                    this.tileManager.UpdateWebsiteTileIfExist(message.Website);
                }
                else
                {
                    this.IsLoading = false;
                    this.HasError = true;
                }
            }
        }
        #endregion
    }
}
